﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace LocalizedResources
{
    public sealed class DataAnnotationsLocalizer
    {
        public static void SetDefaultResourceType(Assembly assembly, Type resources, params Type[] localizableAttributeTypes)
        {
            foreach (var item in GetTypesInNamespace(assembly, null))
            {
                SetDefaultResourceType(item, resources, localizableAttributeTypes);

            }
        }

        public static void SetDefaultResourceType(Assembly assembly, string nameSpace, Type resources, params Type[] localizableAttributeTypes)
        {
            foreach (var item in GetTypesInNamespace(assembly, nameSpace))
            {
                SetDefaultResourceType(item, resources, localizableAttributeTypes);
            }
        }

        public static void SetDefaultResourceType(Type item, Type resources, params Type[] localizableAttributeTypes)
        {
            foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(item))
            {
                foreach (var localizableAttrType in localizableAttributeTypes)
                {
                    Attribute dAttr = ((Attribute)prop.Attributes[localizableAttrType]);
                    if (dAttr != null)
                    {
                        if (dAttr is DisplayAttribute && (dAttr as DisplayAttribute).Name != null)
                            ((DisplayAttribute)dAttr).ResourceType = resources;
                        if (dAttr is ValidationAttribute && (dAttr as ValidationAttribute).ErrorMessageResourceName != null)
                            ((ValidationAttribute)dAttr).ErrorMessageResourceType = resources;

                    }
                }

            }
        }


        public static void ReplaceDefaultLocalizedMessage<T>(Assembly assembly, Type resources, string messageKey) where T : ValidationAttribute
        {
            foreach (var item in GetTypesInNamespace(assembly, null))
            {
                foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(item))
                {
                    ValidationAttribute dAttr = ((ValidationAttribute)prop.Attributes[typeof(T)]);
                    if (dAttr != null)
                    {
                        dAttr.ErrorMessageResourceType = resources;
                        dAttr.ErrorMessageResourceName = messageKey;

                    }

                }

            }
        }

        public static void ReplaceDefaultLocalizedMessage<T>(Assembly assembly, string nameSpace, Type resources, string messageKey) where T : ValidationAttribute
        {
            foreach (var item in GetTypesInNamespace(assembly, nameSpace))
            {
                ReplaceDefaultLocalizedMessage<T>(item ,resources, messageKey);

            }
        }

        public static void ReplaceDefaultLocalizedMessage<T>(Type item, Type resources, string messageKey) where T : ValidationAttribute
        {
            foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(item))
            {
                ValidationAttribute dAttr = ((ValidationAttribute)prop.Attributes[typeof(T)]);
                if (dAttr != null && dAttr.ErrorMessageResourceName == null)
                {
                    dAttr.ErrorMessageResourceType = resources;
                    dAttr.ErrorMessageResourceName = messageKey;
                }

            }
        }

        private static Type[] GetTypesInNamespace(Assembly assembly, string nameSpace)
        {
            if (nameSpace != null)
                return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray();
            else
                return assembly.GetTypes();
        }
    }
}
